#pragma once 
#include<iostream>
#include<queue>
#include<pthread.h>
#include<cstdlib>
#include<ctime>
#include<unistd.h>
using namespace std;
#define NUM 32
template<class T>
class BlockQueue{

  private:
    bool Isfull()
    {
      return q.size()==cap;
    }
    bool Isempty()
    {
      return q.empty();
    }
  public:
 BlockQueue(int _cap=NUM) :cap(_cap)
  {
    pthread_mutex_init(&lock,nullptr);
    pthread_cond_init(&full,nullptr);
    pthread_cond_init(&empty,nullptr);

  }
    void Push(const T& in)
    {
     pthread_mutex_lock(&lock);
     while(Isfull())
     {
        //wait 
        pthread_cond_wait(&full,&lock);//需要等待并自动释放对应的锁
        
     }     
     q.push(in);     
     if(q.size()>=cap/2)
     {
       cout<<"数据很多，消费者来消费"<<endl;
     pthread_cond_signal(&empty);
     }
     pthread_mutex_unlock(&lock);
    }

    void Pop(T& out)
    {
      pthread_mutex_lock(&lock);
      while(Isempty())//必须要用while
      {
        //不能消费，需要等待q有新数据
        pthread_cond_wait(&empty,&lock);//需要等待并自动释放对应的锁
      }    
        out=q.front();
        q.pop();       
      if(q.size()<=cap/2)
      {
        cout<<"数据不多了，快生产"<<endl;
      pthread_cond_signal(&full);

      }
      pthread_mutex_unlock(&lock);
    }
    ~BlockQueue()
    {
      pthread_mutex_destroy(&lock);
      pthread_cond_destroy(&full);
      pthread_cond_destroy(&empty);
    }

  private:
    queue<T> q;//临界资源
    int cap;//数据个数
    pthread_mutex_t lock;
    pthread_cond_t full;
    pthread_cond_t empty;
};

